package com.twu.biblioteca;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.ConcurrentHashMap;

public class Library {

    private final ConcurrentHashMap<String, Book> books;
    private final ConcurrentHashMap<String, Movie> movies;
    private final ConcurrentHashMap<String, User> users = new ConcurrentHashMap<String, User>();

    Library(ConcurrentHashMap<String, Book> books, ConcurrentHashMap<String, Movie> movies) {
        this.books = books;
        this.movies = movies;

    }

    void addUser(User user) {
        users.put(user.getCustomerNumber(), user);
    }

    void displayBookList() {
        System.out.println("\nAvailable books:");
        String formatString = "%-30s %-30s %-5s \n";
        System.out.printf(formatString, "title", "author", "date");
        String divLine = "-------------------------------------------------------------------";
        System.out.println(divLine);
        for (Book book : books.values()) {
            if (!book.isCheckedOut()) {
                System.out.printf(formatString, book.getTitle(), book.getAuthor(), book.getYear());
            }
        }
        System.out.println(divLine + "\n");
    }

    void displayMovieList() {
        System.out.println("\nAvailable movies:");
        String formatString = "%-30s %-5s %-20s %-5s \n";
        System.out.printf(formatString, "title", "year", "director", "rating");
        String divLine = "-------------------------------------------------------------------";
        System.out.println(divLine);
        for (Movie movie : movies.values()) {
            if (!movie.isCheckedOut()) {
                String rating = (movie.getRating() == null ? "unrated" : movie.getRating().toString());
                System.out.printf(formatString, movie.getTitle(),
                        movie.getYear(), movie.getDirector(), rating);
            }
        }
        System.out.println(divLine + "\n");
    }

    boolean isBookCheckedOut(String bookTitle) {
        return books.get(bookTitle).isCheckedOut();
    }

    boolean isMovieCheckedOut(String movieTitle) {
        return movies.get(movieTitle).isCheckedOut();
    }

    String readTitle()
            throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        return br.readLine();
    }

    void checkOutBook(User user) {
        System.out.println("Enter a book title to check-out:");
        while (true) {
            try {
                checkOutBook(readTitle(), user);
                break;
            } catch (IOException e) {
                System.out.println("Please re-enter your book title:");
            } catch (InvalidItemException e) {
                System.out.println("Invalid book. Please re-enter your book title:");
            } catch (UnavailableItemException e) {
                System.out.println("That book is not available.");
                System.out.println("Please re-enter your book title:");
            }

        }

    }

    void checkOutMovie(User user) {
        System.out.println("Enter a movie title to check-out:");
        while (true) {
            try {
                checkOutMovie(readTitle(), user);
                break;
            } catch (IOException e) {
                System.out.println("Please re-enter your movie title:");
            } catch (InvalidItemException e) {
                System.out.println("Invalid movie. Please re-enter your movie title:");
            } catch (UnavailableItemException e) {
                System.out.println("That movie is not available.");
                System.out.println("Please re-enter your movie title:");
            }

        }
    }

    void checkOutMovie(String movieTitle, User user)
            throws InvalidItemException, UnavailableItemException {
        if (!movies.containsKey(movieTitle))
            throw new InvalidItemException(movieTitle);
        Movie movie = movies.get(movieTitle);
        if (movie.isCheckedOut()) {
            throw new UnavailableItemException(movieTitle);
        } else {
            movies.get(movieTitle).checkOut(user);
            System.out.println("Thank you! Enjoy the movie.\n");
        }
        movies.get(movieTitle).checkOut(user);
    }

    void checkOutBook(String bookTitle, User user)
            throws InvalidItemException, UnavailableItemException {
        if (!books.containsKey(bookTitle))
            throw new InvalidItemException(bookTitle);
        Book book = books.get(bookTitle);
        if (book.isCheckedOut()) {
            throw new UnavailableItemException(bookTitle);
        } else {
            books.get(bookTitle).checkOut(user);
            System.out.println("Thank you! Enjoy the book.\n");
        }
    }

    void returnBook(User user) {
        System.out.println("Enter the title of the book you wish to return:");
        while (true) {
            try {
                returnBook(readTitle(), user);
                break;
            } catch (IOException e) {
                System.out.println("Please re-enter your book title:");
            } catch (InvalidItemException e) {
                System.out.println("Invalid book. Please re-enter your book title:");
            }
        }
    }

    void returnBook(String bookTitle, User user)
            throws InvalidItemException {
        if (!books.containsKey(bookTitle))
            throw new InvalidItemException(bookTitle);
        Book book = books.get(bookTitle);
        if (user.hasBook(book)) {
            books.get(bookTitle).returnBook(user);
            System.out.println("Thank you for returning the book.");
        } else {
            throw new InvalidItemException(bookTitle);
        }
    }

     User login(String customerNumber, String password) {
         if (users.containsKey(customerNumber) && users.get(customerNumber).isValidPassword(password)) {
             return users.get(customerNumber);
         }
         return null;
    }
}